/**
 * NO.01 20150703 lin.xin  add wo_id_fk and so_id_fk to sub group condtion
 * NO.02 20150808 Fang.liu add median chart 
 */
package com.service;

import static com.def.GenericDef.SPC_CHART_TYPE_COUNT;
import static com.def.GenericDef.SPC_CHART_TYPE_MEAN;
import static com.def.GenericDef.SPC_CHART_TYPE_MOVING_RANGE;
import static com.def.GenericDef.SPC_CHART_TYPE_RANGE;
import static com.def.GenericDef.SPC_CHART_TYPE_SIGMA;
import static com.def.GenericDef.SPC_CHART_TYPE_SINGLE;
import static com.def.GenericDef.SPC_CHART_TYPE_MEDIAN; //NO.02
import static com.def.GenericDef.SPC_CHART_TYPE_MRANGE; //NO.02
import static com.def.GenericDef.SPC_CHART_TYPE_P; //NO.03
import static com.def.GenericDef.SPC_CHART_TYPE_NP;//NO.03
import static com.def.GenericDef.SPC_CHART_TYPE_C; //NO.03
import static com.def.GenericDef._NORMAL;

import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.List;

import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Service;

import com.dao.IRetPrdInfoDao;
import com.dao.ISpcBisChartMainDao;
import com.dao.ISpcBisGrpDtDao;
import com.dao.ISpcBisGrpMainDao;
import com.dao.ISpcRetChartDataDao;
import com.dao.ISpcRetChartInfoDao;
import com.dao.ISpcRetChartRawDao;
import com.icim.service.ICIMBaseService;
import com.model.Spc_bis_chart_main;
import com.model.Spc_bis_grp_dt;
import com.model.Spc_bis_grp_main;
import com.model.Spc_bis_grp_mainId;
import com.model.Spc_ret_chart_data;
import com.model.Spc_ret_chart_dataId;
import com.model.Spc_ret_chart_info;
import com.model.Spc_ret_chart_infoId;
import com.model.Spc_ret_chart_raw;
import com.model.Spc_ret_chart_rawId;
import com.rtnBean.SpcRuleRltObj;
import com.rtnBean.spc.DataGroupItem;
import com.rtnBean.spc.PrdSeqItem;
import com.rtnBean.spc.SpcItem;
import com.rtnBean.spc.ValueItem;
import com.tx.Xpspcchk.XpspcchkI;
import com.tx.Xpspcchk.XpspcchkIA;
import com.tx.Xpspcchk.XpspcchkO;
import com.util.MqOpe;
import com.util.Util;

@Scope("prototype")
@Service("XpspcchkService")
public class XpspcchkService extends ICIMBaseService {
	private static final Logger logger = Logger.getLogger(XpspcchkService.class);
	private static final String _AND = " AND ";
	private static final int MAX_SPC_VALUE_CNT = 20;
	@Autowired
	XpspcchkI inTrx;
	@Autowired
	XpspcchkO outTrx;

	@Autowired
	IRetPrdInfoDao retPrdInfoDao;

	@Autowired
	ISpcBisGrpDtDao spcBisGrpDtDao;
	@Autowired
	ISpcBisGrpMainDao spcBisGrpMainDao;
	@Autowired
	ISpcBisChartMainDao spcBisChartMainDao;
	@Autowired
	ISpcRetChartInfoDao spcRetChartInfoDao;
	@Autowired
	ISpcRetChartDataDao spcRetChartDataDao;
	@Autowired
	ISpcRetChartRawDao spcRetChartRawDao;

	//Global variables 
	private String gszMsgBuf = "";
	private SpcItem spcItem = new SpcItem();

	public String subMainProc(String strInMsg) {
		MqOpe mqOpe = new MqOpe();
		String reply = "";
		outTrx.setTrx_id("XPSPCCHK");
		outTrx.setType_id("O");
		try {
			logger.info("InTrx is " + strInMsg);
			inTrx = (XpspcchkI) mqOpe.inStr2Obj(strInMsg, inTrx);
			long lRc = SubMainProc2();
			if (lRc != _NORMAL) {
				outTrx.setRtn_code("000000" + lRc);
				outTrx.setRtn_msg(gszMsgBuf);
			}
			outTrx.setRtn_code("0000000");
			outTrx.setRtn_msg("success");
		} catch (Exception ex) {
			logger.info(ex.toString());
			outTrx.setRtn_code("0000001");
			outTrx.setRtn_msg(Util.stackTraceToString(ex));
			logger.error(Util.stackTraceToString(ex));
		} finally {
			reply = mqOpe.obj2Str(outTrx);
			logger.info(reply);
		}
		return reply;
	}

	/****************
	1 向 spc_ret_mfg_data 存入EDC 信息
	2
	   如果oper表upcorspnd_id不为空,向acorspnd表中写入数据,
	   如果oper表dncorspnd_id不为空,去acorspnd表读取，
	
	  IF(COUNT>0){
	    用acorspnd表中的数据 给p_tool_id,p_ope_id等字段赋值
	  }
	  IF(p_tool_id==m_tool_id){
	    collection_typ = 2;
	  }ELSE{
	    collection_typ = 1;
	  }
	  -- 判断类型 
	3 读取spc_bis_grp_dt表，选择符合条件的GROUP 
	  SELECT * FROM spc_bis_gr_dt WHERE collection_typ='2' AND  
	      (bis_tool_id ='CIPOL220' AND bis_tool_id ='*')     AND
	-- TODO:MDL_TYP_FK ='123' and mdl_typ_fk='*'             and 
	-- TODO:mdl_cate_fk
	      (mdl_id_fk ='132'     OR mdl_id_fk   ='*')   AND 
	      (recipe_id_fk ='123'  OR recipe_id_fk='*')   AND 
	      (path_id_fk   ='123'  OR PATH_ID_FK  ='*')   AND
	      (path_ver_id  ='123'  OR paht_ver_id ='*')   AND
	      (ope_no_fk    ='0200' OR ope_no_fk   ='*')   AND 
	      (ope_id_fk    ='0100' OR ope_id_fk   ='*')   AND
	      (ope_ver_fk   ='0000' OR ope_ver_fk  ='*')   AND
	      (proc_id      ='PI'   OR proc_id     ='*')    
	
	4 读取spc_bis_grp_main表 看此GROUP 是否存在
	5 FOR(INT i=0;i<iary.length;i++){
		 SELECT * FROM spc_bis_chart_main WHERE collection_typ='2' AND gno='?'
		 AND  data_group_fk= iary[i].data_group
		 
		 IF(COUNT<=0){
		   CONTINUE;
		 }
		   	
		 (1)根据chart_type_fk判断类型,按相应方式计算存入 spc_bis_chart_data ,shift spc_bis_chart_info data1 TO data15
		 (2)解析规则和CHART_SPEC_CHK_FLG，判断是否超规则。并将结果写入spc_bis_chart_data和spc_bis_char_info(BOTH rule result AND flg)
	     (3)预留发送mail hold货接口
		 
	  } 
	
	****************/
	/**
	 * @param xpsiqcinI
	 * @return 
	 */
	public long SubMainProc2() {

		List<XpspcchkIA> iaryList = inTrx.getIary();

		String colTyp = "2";
		String mdlId = inTrx.getMdl_id();
		String pToolId = inTrx.getP_tool_id();
		String pRecipeId = inTrx.getP_recipe_id();
		String pPathId = inTrx.getP_path_id();
		String pPathVer = inTrx.getP_path_ver();
		String pOpeNo = inTrx.getP_ope_no();
		String pOpeId = inTrx.getP_ope_id();
		String pOpeVer = inTrx.getP_ope_ver();
		String pProcId = inTrx.getP_proc_id();
		String woId = inTrx.getWo_id_fk();
		String cusId = inTrx.getCus_id_fk();
		String soId = inTrx.getSo_id_fk();

		String prdSeqId = inTrx.getProd_seq_id();
		String evtUsr = inTrx.getEvt_usr();

		setSpcItem();

		if ("Y".equals(inTrx.getCdpc_flg())) {
			cdpcSpcProc(iaryList, colTyp, mdlId, pToolId, pRecipeId, pPathId, pPathVer, pOpeNo, pOpeId, pOpeVer, pProcId, woId,
					soId, cusId, prdSeqId, evtUsr);
		} else {
			normalSpcProc(iaryList, colTyp, mdlId, pToolId, pRecipeId, pPathId, pPathVer, pOpeNo, pOpeId, pOpeVer, pProcId, woId,
					soId, cusId, prdSeqId, evtUsr);

		}

		return _NORMAL;
	}

	private void cdpcSpcProc(List<XpspcchkIA> iaryList, String colTyp, String mdl_id, String p_tool_id, String p_recipe_id,
			String p_path_id, String p_path_ver, String p_ope_no, String p_ope_id, String p_ope_ver, String p_proc_id,
			String wo_id, String so_id, String cus_id, String prd_seq_id, String evt_usr) {
		Double thickness = inTrx.getTarget_thickness();
		String thicknessType = inTrx.getThickness_type();
		//		

		for (int jx = 0; !spcItem.getPrdSeqList().isEmpty() && jx < spcItem.getPrdSeqList().get(0).getData_group_cnt(); jx++) {
			DataGroupItem dataGroupItem = spcItem.getPrdSeqList().get(0).getDataGroupList().get(jx);
			String dataGroup = dataGroupItem.getData_group();

			List<ValueItem> valueItemList = dataGroupItem.getData_valueList();
			List<Double> valueList = new ArrayList<Double>();
			for (ValueItem valueItem : valueItemList) {
				valueList.add(valueItem.getData_value());
			}

			Double chartValue = Double.valueOf(iaryList.get(jx).getData_value());

			/**
			 * find chart that satisfying the conditions containing data_group and target
			 */
			String hql = "FROM Spc_ret_chart_info where col_typ_fk = ? and data_group_fk = ? and chart_target = ? and chart_ack_flg = ? and chart_typ_fk in ('01','10','20','30','40','50')";
			List<Spc_ret_chart_info> mainSpcRetChartInfoList = spcRetChartInfoDao.list(hql, 2, dataGroup, thickness,thicknessType);
			for (Spc_ret_chart_info mainSpcRetChartInfo : mainSpcRetChartInfoList) {

				/**
				 * list main and slave chart by grp_no ,chart_no 
				 */
				hql = "FROM Spc_ret_chart_info where col_typ_fk = ? and grp_no_fk = ? and chart_no_fk = ? ";

				List<Spc_ret_chart_info> spcRetChartInfoList = spcRetChartInfoDao.list(hql, 2, mainSpcRetChartInfo.getId()
 						.getGrp_no_fk(), mainSpcRetChartInfo.getId().getChart_no_fk());

				reportSpcProc(colTyp, mdl_id, p_tool_id, p_recipe_id, p_path_id, p_ope_no, p_ope_id, p_proc_id, wo_id, so_id,
						cus_id, prd_seq_id, evt_usr, "00", valueItemList, valueList, chartValue, spcRetChartInfoList);
			}

		}
	}

	private void normalSpcProc(List<XpspcchkIA> iaryList, String colTyp, String mdlId, String pToolId, String pRecipeId,
			String pPathId, String pPathVer, String pOpeNo, String pOpeId, String pOpeVer, String pProcId, String woId,
			String soId, String cusId, String prdSeqId, String evtUsr) {
		StringBuffer sqlBuffer = new StringBuffer();
		sqlBuffer.append("FROM Spc_bis_grp_dt where col_typ_fk= ? ");
		sqlBuffer.append(_AND).append("( tool_id_fk=? OR tool_id_fk='*') ");
		sqlBuffer.append(_AND).append("( mdl_id_fk=? OR mdl_id_fk='*') ");
		sqlBuffer.append(_AND).append("( recipe_id_fk=? OR recipe_id_fk='*') ");
		sqlBuffer.append(_AND).append("( path_id_fk=? OR path_id_fk='*') ");
		sqlBuffer.append(_AND).append("( path_ver_fk=? OR path_ver_fk='*') ");
		sqlBuffer.append(_AND).append("( ope_no_fk=? OR ope_no_fk='*') ");
		sqlBuffer.append(_AND).append("( ope_id_fk=? OR ope_id_fk='*') ");
		sqlBuffer.append(_AND).append("( ope_ver_fk=? OR ope_ver_fk='*') ");
		sqlBuffer.append(_AND).append("( proc_id=? OR proc_id='*') ");
		sqlBuffer.append(_AND).append("( wo_id_fk=? OR wo_id_fk='*') ");
		sqlBuffer.append(_AND).append("( cus_id_fk=? OR cus_id_fk='*') ");
		sqlBuffer.append(" ORDER BY col_typ_fk,grp_no_fk ");

		List<Spc_bis_grp_dt> spcBisGrpDtList = spcBisGrpDtDao.list(sqlBuffer.toString(), colTyp, pToolId, mdlId, pRecipeId,
				pPathId, pPathVer, pOpeNo, pOpeId, pOpeVer, pProcId, woId, cusId);

		if (spcBisGrpDtList.isEmpty()) {
			gszMsgBuf = "not found Spc_bis_gr_dt";
			logger.warn(gszMsgBuf);
			return;
		}
		for (int ix = 0; ix < spcBisGrpDtList.size(); ix++) {
			//不可以出现一个点进入一张chart两次的情况
			if (ix > 0) {
				if (spcBisGrpDtList.get(ix).getId().getGrp_no_fk().equals(spcBisGrpDtList.get(ix - 1).getId().getGrp_no_fk())
						&& spcBisGrpDtList.get(ix).getId().getCol_typ_fk()
								.equals(spcBisGrpDtList.get(ix - 1).getId().getCol_typ_fk())) {
					continue;
				}
			}
			Spc_bis_grp_mainId spcBisGrpMainId = new Spc_bis_grp_mainId();

			String grpNo = spcBisGrpDtList.get(ix).getId().getGrp_no_fk();
			String subGrpNo = spcBisGrpDtList.get(ix).getId().getSub_grp_no();

			spcBisGrpMainId.setCol_typ(colTyp);
			spcBisGrpMainId.setGrp_no(grpNo);
			Spc_bis_grp_main spcBisGrpMain = spcBisGrpMainDao.get(spcBisGrpMainId);
			if (spcBisGrpMain == null) {
				gszMsgBuf = "not found spc_bis_grp_main";
				logger.info(gszMsgBuf);
				return;
			}

			for (int jx = 0; !spcItem.getPrdSeqList().isEmpty() && jx < spcItem.getPrdSeqList().get(0).getData_group_cnt(); jx++) {

				DataGroupItem dataGroupItem = spcItem.getPrdSeqList().get(0).getDataGroupList().get(jx);
				String dataGroup = dataGroupItem.getData_group();

				sqlBuffer.setLength(0);
				sqlBuffer.append(" FROM Spc_bis_chart_main WHERE id.col_typ_fk= ?");
				sqlBuffer.append(" and id.grp_no_fk= ?");
				sqlBuffer.append(" and data_group_fk= ?");

				List<Spc_bis_chart_main> spcBisChartMainList = spcBisChartMainDao.list(sqlBuffer.toString(), colTyp,
						grpNo, dataGroup);
				if (spcBisChartMainList.isEmpty()) {
					continue;
				}
				for (Spc_bis_chart_main spcBisChartMain : spcBisChartMainList) {
					String chartNo = spcBisChartMain.getId().getChart_no();

					List<ValueItem> valueItemList = dataGroupItem.getData_valueList();
					List<Double> valueList = new ArrayList<Double>();
					for (ValueItem valueItem : valueItemList) {
						valueList.add(valueItem.getData_value());
					}

					Double chartValue = Double.valueOf(iaryList.get(jx).getData_value());

					String hql = "FROM Spc_ret_chart_info where id.col_typ_fk = ? AND id.grp_no_fk = ? AND id.chart_no_fk = ? ";
					List<Spc_ret_chart_info> spcRetChartInfoList = spcRetChartInfoDao.list(hql, colTyp, grpNo, chartNo);
					if (spcRetChartInfoList.isEmpty()) {
						logger.error("not found Record in spc_bis_chart_info");
						continue;
					}
					reportSpcProc(colTyp, mdlId, pToolId, pRecipeId, pPathId, pOpeNo, pOpeId, pProcId, woId, soId, cusId, prdSeqId,
							evtUsr, subGrpNo, valueItemList, valueList, chartValue, spcRetChartInfoList);
				}
				
			}
		}
	}

	private void reportSpcProc(String colTyp, String mdl_id, String p_tool_id, String p_recipe_id, String p_path_id,
			String p_ope_no, String p_ope_id, String p_proc_id, String wo_id, String so_id, String cus_id, String prd_seq_id,
			String evt_usr, String sub_grp_no, List<ValueItem> valueItemList, List<Double> valueList, Double chartValue,
			List<Spc_ret_chart_info> spcRetChartInfoList) {

		Timestamp proc_timestamp = Util.getCurrentTimestamp(); //NO.03

		//		 chartNo, dataValue, chartValue,

		for (Spc_ret_chart_info spcRetChartInfo : spcRetChartInfoList) {
			Spc_ret_chart_infoId spcRetChartInfoId = spcRetChartInfo.getId();
			String grpNo = spcRetChartInfoId.getGrp_no_fk();
			String chartNo = spcRetChartInfoId.getChart_no_fk();
			String chartTyp = spcRetChartInfoId.getChart_typ_fk();
			if (chartTyp.equals(SPC_CHART_TYPE_SINGLE)) {
				//多点只进 mean chart ,不进 single chart
				if (valueList.size() != 1) {
					continue;
				}
				chartValue = chartValue;
			} else if (chartTyp.equals(SPC_CHART_TYPE_MOVING_RANGE)) {
				//多点只进 mean chart ,不进 single chart
				if (valueList.size() != 1) {
					continue;
				}
				//get previous chart value : single chart's (main chart) chart_value
				String mainSpcRetChartInfoSql = "FROM Spc_ret_chart_info where col_typ_fk =? and grp_no_fk = ? and chart_no_fk = ? and chart_typ_fk = ?";
				Spc_ret_chart_info mainSpcRetChartInfo = spcRetChartInfoDao.uniqueResult(mainSpcRetChartInfoSql,
						spcRetChartInfoId.getCol_typ_fk(), spcRetChartInfoId.getGrp_no_fk(), spcRetChartInfoId.getChart_no_fk(),
						SPC_CHART_TYPE_SINGLE);
				Double pvChartvalue = mainSpcRetChartInfo.getChart_l_value19();

				//第一个点不计入Moving Range Chart
				if (pvChartvalue == null) {
					continue;
					//							pvChartvalue = Double.valueOf("0");
				}
				chartValue = Math.abs(chartValue - pvChartvalue);
			} else if (chartTyp.equals(SPC_CHART_TYPE_MEAN)) {
				//一个点不允许进 mean chart 
				if (valueList.size() < 2) {
					continue;
				}
				chartValue = getAveArray(valueList);
			} else if (chartTyp.equals(SPC_CHART_TYPE_RANGE)) {
				//一个点不允许进 mean chart 
				if (valueList.size() < 2) {
					continue;
				}
				Double maxValue = getMaxArray(valueList);
				Double minValue = getMinArray(valueList);
				chartValue = maxValue - minValue;
			} else if (chartTyp.equals(SPC_CHART_TYPE_SIGMA)) {
				//一个点不允许进 mean chart 
				if (valueList.size() < 2) {
					continue;
				}
				chartValue = getSigmaArray(valueList);
			} else if (chartTyp.equals(SPC_CHART_TYPE_COUNT)) {
				//TODO
			} else if (chartTyp.equals(SPC_CHART_TYPE_MEDIAN)) { //NO.02
				if (valueList.size() < 2) {
					continue;
				}
				chartValue = getMedianArray(valueList);
			} else if (chartTyp.equals(SPC_CHART_TYPE_MRANGE)) { //NO.02
				if (valueList.size() < 2) {
					continue;
				}
				Double maxValue = getMaxArray(valueList);
				Double minValue = getMinArray(valueList);
				chartValue = maxValue - minValue;
			} else {
				chartValue = chartValue;
			}
			if(chartTyp.equals(SPC_CHART_TYPE_SINGLE)||chartTyp.equals(SPC_CHART_TYPE_MEAN) 
					|| chartTyp.equals(SPC_CHART_TYPE_P)||chartTyp.equals(SPC_CHART_TYPE_NP) || chartTyp.equals(SPC_CHART_TYPE_C)){
						
					spcRetChartInfo = ruleCalucate(spcRetChartInfo, chartValue); //NO.03
			}

			//count chart process, their 
			if (chartTyp.equals(SPC_CHART_TYPE_P) || chartTyp.equals(SPC_CHART_TYPE_NP) || chartTyp.equals(SPC_CHART_TYPE_C)) {
				for (int x = 0; x < valueItemList.size(); x++) {

					chartValue = valueItemList.get(x).getData_value();

					Double dInputTime = Util.getDoubleTime();

					addSpcRetChartDataProc(colTyp, mdl_id, p_tool_id, p_recipe_id, p_path_id, p_ope_no, p_ope_id, p_proc_id,
							so_id, wo_id, cus_id, prd_seq_id, evt_usr, grpNo, sub_grp_no, valueList, chartNo, chartValue,
							spcRetChartInfo, chartTyp, dInputTime);

				}
			} else {
				double dInputTime = Util.getDoubleTime();

				addSpcRetChartDataProc(colTyp, mdl_id, p_tool_id, p_recipe_id, p_path_id, p_ope_no, p_ope_id, p_proc_id, wo_id,
						so_id, cus_id, prd_seq_id, evt_usr, grpNo, sub_grp_no, valueList, chartNo, chartValue, spcRetChartInfo,
						chartTyp, dInputTime);

				if (chartTyp.equals(SPC_CHART_TYPE_MEAN) || chartTyp.equals(SPC_CHART_TYPE_MEDIAN)) {

					addSpcRetChartRawProc(colTyp, prd_seq_id, grpNo, sub_grp_no, proc_timestamp, valueItemList, chartNo,
							dInputTime);

				}
			}

		}
	}

	private void addSpcRetChartRawProc(String colTyp, String prd_seq_id, String grpNo, String sub_grp_no,
			Timestamp proc_timestamp, List<ValueItem> valueItemList, String chartNo, double dInputTime) {
		for (int i = 0; i < valueItemList.size(); i++) {
			ValueItem valueItem = valueItemList.get(i);

			Spc_ret_chart_raw spc_ret_chart_raw = new Spc_ret_chart_raw();
			Spc_ret_chart_rawId spc_ret_chart_rawId = new Spc_ret_chart_rawId();
			spc_ret_chart_rawId.setCol_typ_fk(colTyp);
			spc_ret_chart_rawId.setGrp_no_fk(grpNo);
			spc_ret_chart_rawId.setChart_no_fk(chartNo);
			spc_ret_chart_rawId.setProc_time_d(dInputTime);
			spc_ret_chart_rawId.setPrd_value_seq(i);
			spc_ret_chart_rawId.setSub_grp_no(sub_grp_no);
			spc_ret_chart_raw.setId(spc_ret_chart_rawId);
			spc_ret_chart_raw.setProc_timestamp(proc_timestamp);
			spc_ret_chart_raw.setPrd_seq_id_fk(prd_seq_id);
			spc_ret_chart_raw.setData_group_seq_fk(valueItem.getData_group_seq());
			spc_ret_chart_raw.setPrd_raw_value(valueItem.getData_value());

			spcRetChartRawDao.save(spc_ret_chart_raw);
		}
	}

	private void addSpcRetChartDataProc(String colTyp, String mdl_id, String p_tool_id, String p_recipe_id, String p_path_id,
			String p_ope_no, String p_ope_id, String p_proc_id, String wo_id, String so_id, String cus_id, String prd_seq_id,
			String evt_usr, String grpNo, String sub_grp_no, List<Double> valueList, String chartNo, Double chartValue,
			Spc_ret_chart_info spcRetChartInfo, String chart_typ, Double dInputTime) {
		String lot_id = inTrx.getLot_id_fk();
		String m_tool_id = inTrx.getM_tool_id();
		String m_recipe_id = inTrx.getM_recipe_id();
		String todoSpace = " ";

		Spc_ret_chart_data spc_ret_chart_data = new Spc_ret_chart_data();
		Spc_ret_chart_dataId spc_ret_chart_dataId = new Spc_ret_chart_dataId();
		spc_ret_chart_dataId.setCol_typ_fk(colTyp);
		spc_ret_chart_dataId.setGrp_no_fk(grpNo);
		spc_ret_chart_dataId.setChart_no_fk(chartNo);
		spc_ret_chart_dataId.setChart_typ_fk(chart_typ);
		spc_ret_chart_dataId.setInput_time_d(dInputTime);
		spc_ret_chart_data.setId(spc_ret_chart_dataId);
		spc_ret_chart_data.setInput_timestamp(Util.getCurrentTimestamp());
		spc_ret_chart_data.setProc_timestamp(inTrx.getEvt_timestamp());
		spc_ret_chart_data.setSub_grp_no_fk(sub_grp_no);
		spc_ret_chart_data.setEvt_usr(evt_usr);
		spc_ret_chart_data.setPrd_seq_id_fk(prd_seq_id);
		spc_ret_chart_data.setExd_flg(todoSpace);
		spc_ret_chart_data.setChart_value(chartValue);
		spc_ret_chart_data.setSample_size_fk(valueList.size());
		spc_ret_chart_data.setChart_spec_rlt_fk(spcRetChartInfo.getChart_spec_rlt());
		spc_ret_chart_data.setChart_rule_1_rlt_fk(spcRetChartInfo.getChart_rule_1_rlt());
		spc_ret_chart_data.setChart_rule_2_rlt_fk(spcRetChartInfo.getChart_rule_2_rlt());
		spc_ret_chart_data.setOoc_ocap_fk(todoSpace);
		spc_ret_chart_data.setOos_ocap_fk(todoSpace);
		spc_ret_chart_data.setChart_total_action_fk(spcRetChartInfo.getChart_total_action());
		spc_ret_chart_data.setChart_detail_action_fk(todoSpace);
		spc_ret_chart_data.setChart_usl_fk(spcRetChartInfo.getChart_usl()); //NO.03
		spc_ret_chart_data.setChart_lsl_fk(spcRetChartInfo.getChart_lsl()); //NO.03
		spc_ret_chart_data.setChart_ucl_fk(spcRetChartInfo.getChart_ucl()); //NO.03
		spc_ret_chart_data.setChart_lcl_fk(spcRetChartInfo.getChart_lcl()); //NO.03
		spc_ret_chart_data.setChart_uwl_fk(spcRetChartInfo.getChart_uwl()); //NO.03
		spc_ret_chart_data.setChart_lwl_fk(spcRetChartInfo.getChart_lwl()); //NO.03
		spc_ret_chart_data.setChart_mean_fk(spcRetChartInfo.getChart_mean()); //NO.03

		spc_ret_chart_data.setMdl_id_fk(mdl_id);
		spc_ret_chart_data.setP_tool_id_fk(p_tool_id);
		spc_ret_chart_data.setP_recipe_id_fk(p_recipe_id);
		spc_ret_chart_data.setP_path_id_fk(p_path_id);
		spc_ret_chart_data.setP_ope_no_fk(p_ope_no);
		spc_ret_chart_data.setP_ope_id_fk(p_ope_id);
		spc_ret_chart_data.setP_proc_id(p_proc_id);
		spc_ret_chart_data.setM_tool_id_fk(m_tool_id);
		spc_ret_chart_data.setM_recipe_id_fk(m_recipe_id);
		spc_ret_chart_data.setLot_id_fk(lot_id);
		spc_ret_chart_data.setCus_id_fk(cus_id);
		spc_ret_chart_data.setWo_id_fk(wo_id);
		spc_ret_chart_data.setSo_id_fk(so_id);
		spcRetChartDataDao.save(spc_ret_chart_data);
	}

	public String getRuleResult(char rule, boolean isBreakRule, String chart_rlt) {
		if (rule == 'H') {
			if (isBreakRule == true) {
				return chart_rlt + "H";
			} else {
				return chart_rlt + "N";
			}
		} else if (rule == 'W') {
			if (isBreakRule == true) {
				return chart_rlt + "W";
			} else {
				return chart_rlt + "N";
			}
		}
		return chart_rlt + "N";
	}

	public boolean getHoldFlg(SpcRuleRltObj spcRuleObj, boolean isBreakRule) {
		if (spcRuleObj.isHold_flg() == true || isBreakRule == true) {
			return true;
		}
		return false;
	}

	public long sendAlarm(String message) {

		return _NORMAL;
	}

	public void setSpcItem() {
		PrdSeqItem prdSeqItem = new PrdSeqItem();
		List<PrdSeqItem> prdSeqList = new ArrayList<PrdSeqItem>();
		List<DataGroupItem> dataGroupList = new ArrayList<DataGroupItem>();
		List<XpspcchkIA> iaryList = inTrx.getIary();
		List<String> dgStringList = new ArrayList<String>();
		String data_group;
		for (XpspcchkIA iary : iaryList) {
			data_group = iary.getData_group();
			if (dataGroupList.size() == 0) {
				DataGroupItem dataGroupItem = new DataGroupItem();
				dataGroupItem.setData_group(data_group);
				List<ValueItem> valueItemList = new ArrayList<ValueItem>();
				ValueItem firstValueItem = new ValueItem();
				firstValueItem.setData_group_seq(iary.getData_group_seq());
				firstValueItem.setData_value(Double.valueOf(iary.getData_value()));
				valueItemList.add(firstValueItem);
				for (int i = 1; i < iaryList.size(); i++) {
					if (iaryList.get(i).getData_group().equals(data_group)) {
						//						valueList.add(Double.valueOf( iaryList.get(i).getData_value() ));
						ValueItem valueItem = new ValueItem();
						valueItem.setData_group_seq(iaryList.get(i).getData_group_seq());
						valueItem.setData_value(Double.valueOf(iaryList.get(i).getData_value()));
						valueItemList.add(valueItem);
					}
				}
				dataGroupItem.setData_valueList(valueItemList);
				dataGroupItem.setValue_cnt(valueItemList.size());

				dataGroupList.add(dataGroupItem);
				dgStringList.add(data_group);
			} else {
				boolean isExist = false;
				for (String dgString : dgStringList) {
					if (dgString.equals(data_group)) {
						isExist = true;
						break;
					}
				}
				if (isExist == true) {
					continue;
				}
				DataGroupItem dataGroupItem = new DataGroupItem();
				dataGroupItem.setData_group(data_group);
				List<ValueItem> valueItemList = new ArrayList<ValueItem>();
				for (int i = 1; i < iaryList.size(); i++) {
					if (iaryList.get(i).getData_group().equals(data_group)) {
						//						valueList.add(Double.valueOf( iaryList.get(i).getData_value() ));
						ValueItem valueItem = new ValueItem();
						valueItem.setData_group_seq(iaryList.get(i).getData_group_seq());
						valueItem.setData_value(Double.valueOf(iaryList.get(i).getData_value()));
						valueItemList.add(valueItem);
					}
				}
				dataGroupItem.setData_valueList(valueItemList);
				dataGroupItem.setValue_cnt(valueItemList.size());
				dataGroupList.add(dataGroupItem);

				dgStringList.add(data_group);
			}
		}
		prdSeqItem.setData_group_cnt(dataGroupList.size());
		prdSeqItem.setDataGroupList(dataGroupList);
		prdSeqList.add(prdSeqItem);
		spcItem.setPrdSeqList(prdSeqList);
		spcItem.setPrd_seq_cnt(1);
	}

	public Double getMaxArray(List<Double> valueList) {
		Double maxValue = valueList.get(0);
		for (int i = 0; i < valueList.size(); i++) {
			if (valueList.get(i) > maxValue) {
				maxValue = valueList.get(i);
			}
		}
		return maxValue;
	}

	public Double getMinArray(List<Double> valueList) {
		Double minValue = valueList.get(0);
		for (int i = 0; i < valueList.size(); i++) {
			if (valueList.get(i) < minValue) {
				minValue = valueList.get(i);
			}
		}
		return minValue;
	}

	public Double getAveArray(List<Double> valueList) {
		Double valueSum = Double.valueOf(0);
		for (Double d : valueList) {
			valueSum = valueSum + d;
		}
		return (valueSum / valueList.size());
	}

	public Double getSigmaArray(List<Double> valueList) {
		int cnt = valueList.size();
		Double average = getAveArray(valueList);
		double temp = 0;
		for (int i = 0; i < cnt; i++) {
			temp = temp + Math.pow((valueList.get(i) - average), 2);
		}
		temp = temp / (cnt - 1);

		return Math.sqrt(temp);

	}

	public boolean isEmpty(Double d) {
		return d == null || d == 0 ? true : false;
	}

	public Spc_ret_chart_info ruleCalucate(Spc_ret_chart_info spcRetChartInfo, Double chartValue) {
		boolean holdFlg = false;
		String chart_rule1_rlt = "";

		Double value1 = spcRetChartInfo.getChart_l_value02();
		Double value2 = spcRetChartInfo.getChart_l_value03();
		Double value3 = spcRetChartInfo.getChart_l_value04();
		Double value4 = spcRetChartInfo.getChart_l_value05();
		Double value5 = spcRetChartInfo.getChart_l_value06();
		Double value6 = spcRetChartInfo.getChart_l_value07();
		Double value7 = spcRetChartInfo.getChart_l_value08();
		Double value8 = spcRetChartInfo.getChart_l_value09();
		Double value9 = spcRetChartInfo.getChart_l_value10();
		Double value10 = spcRetChartInfo.getChart_l_value11();
		Double value11 = spcRetChartInfo.getChart_l_value12();
		Double value12 = spcRetChartInfo.getChart_l_value13();
		Double value13 = spcRetChartInfo.getChart_l_value14();
		Double value14 = spcRetChartInfo.getChart_l_value15();
		Double value15 = spcRetChartInfo.getChart_l_value16();
		Double value16 = spcRetChartInfo.getChart_l_value17();
		Double value17 = spcRetChartInfo.getChart_l_value18();
		Double value18 = spcRetChartInfo.getChart_l_value19();
		Double value19 = spcRetChartInfo.getChart_l_value20();
		Double value20 = chartValue;

		Double[] values = new Double[] { value1, value2, value3, value4, value5, value6, value7, value8, value9, value10,
				value11, value12, value13, value14, value15, value16, value17, value18, value19, value20 };

		spcRetChartInfo.setChart_l_value01(value1);
		spcRetChartInfo.setChart_l_value02(value2);
		spcRetChartInfo.setChart_l_value03(value3);
		spcRetChartInfo.setChart_l_value04(value4);
		spcRetChartInfo.setChart_l_value05(value5);
		spcRetChartInfo.setChart_l_value06(value6);
		spcRetChartInfo.setChart_l_value07(value7);
		spcRetChartInfo.setChart_l_value08(value8);
		spcRetChartInfo.setChart_l_value09(value9);
		spcRetChartInfo.setChart_l_value10(value10);
		spcRetChartInfo.setChart_l_value11(value11);
		spcRetChartInfo.setChart_l_value12(value12);
		spcRetChartInfo.setChart_l_value13(value13);
		spcRetChartInfo.setChart_l_value14(value14);
		spcRetChartInfo.setChart_l_value15(value15);
		spcRetChartInfo.setChart_l_value16(value16);
		spcRetChartInfo.setChart_l_value17(value17);
		spcRetChartInfo.setChart_l_value18(value18);
		spcRetChartInfo.setChart_l_value19(value19);
		spcRetChartInfo.setChart_l_value20(value20);

		Double usl = spcRetChartInfo.getChart_usl();
		Double lsl = spcRetChartInfo.getChart_lsl();
		Double ucl = spcRetChartInfo.getChart_ucl();
		Double lcl = spcRetChartInfo.getChart_lcl();
		Double uwl = spcRetChartInfo.getChart_uwl();
		Double lwl = spcRetChartInfo.getChart_lwl();
		Double target = spcRetChartInfo.getChart_target();
		//Check OOS
		if (("Y").equals(spcRetChartInfo.getChart_spec_chk_flg())) {
			if (chartValue > usl) {
				spcRetChartInfo.setChart_spec_rlt("U");
				//					spcRuleRltObj.setChart_spec_rlt_fk("U");
				holdFlg = true;
			} else if (chartValue < lsl) {
				spcRetChartInfo.setChart_spec_rlt("L");
				//					spcRuleRltObj.setChart_spec_rlt_fk("L");
				holdFlg = true;
			} else {
				spcRetChartInfo.setChart_spec_rlt("N");
				//					spcRuleRltObj.setChart_spec_rlt_fk("N");
			}
		}
		//Check WE Rule
		String chart_rule1 = spcRetChartInfo.getChart_rule_1_info();
		if (chart_rule1 != null && chart_rule1.length() >= 7) {
			char rule1 = chart_rule1.charAt(0);//OOC
			char rule2 = chart_rule1.charAt(1);
			char rule3 = chart_rule1.charAt(2);
			char rule4 = chart_rule1.charAt(3);
			char rule5 = chart_rule1.charAt(4);
			char rule6 = chart_rule1.charAt(5);
			char rule7 = chart_rule1.charAt(6);

			String ruleCheckedRlt = "N";
			//八条 rule 这里只写第一条OOC的逻辑

			if ('Y' == rule1) {
				if (chartValue > ucl || chartValue < lcl) {
					//								chart_rule1_rlt = getRuleResult( rule1 , true ,chart_rule1_rlt);
					holdFlg = true;
					ruleCheckedRlt = "Y";
					//								spcRuleRltObj.setChart_total_action_fk("H");
				} else {
					//								chart_rule1_rlt = getRuleResult( rule1 , false ,chart_rule1_rlt);
					//								spcRuleRltObj.setChart_total_action_fk("N");
				}
			}
			chart_rule1_rlt = chart_rule1_rlt + ruleCheckedRlt;

			//rule 2 :连续8点在同一侧
			int rule2ContinueAboveResult = 0;
			int rule2ContinueBlowResult = 0;
			ruleCheckedRlt = "N";
			if ('Y' == rule2) {
				int counter = 0;
				for (counter = 0; counter < 8; counter++) {
					Double tmpValue = values[MAX_SPC_VALUE_CNT - 1 - counter];
					if(tmpValue == null){
						continue;
					}
					if ( tmpValue> target) {
						rule2ContinueAboveResult++;
					}
					if ( tmpValue < target) {
						rule2ContinueBlowResult++;
					}
					if (rule2ContinueAboveResult > 8 || rule2ContinueBlowResult > 8) {
						ruleCheckedRlt = "Y";
					}
				}
			}

			chart_rule1_rlt = chart_rule1_rlt + ruleCheckedRlt;

			//rule3 : 连续6点持续上升

			int rule3ContinueAscResult = 0;
			int rule3ContinueDescResult = 0;

			ruleCheckedRlt = "N";
			if ('Y' == rule3) {
				for (int i = 0; i < 5; i++) {
					Double firstValue = values[MAX_SPC_VALUE_CNT - 1 - i];
					Double secondValue = values[MAX_SPC_VALUE_CNT - 2 - i];
					if (!isEmpty(firstValue) && !isEmpty(secondValue) && firstValue > secondValue) {
						rule3ContinueAscResult++;
					}
					if (!isEmpty(firstValue) && !isEmpty(secondValue) && firstValue < secondValue) {
						rule3ContinueDescResult++;
					}
				}
				if (rule3ContinueAscResult >= 5 || rule3ContinueDescResult >= 5) {
					ruleCheckedRlt = "Y";
				}

			}

			chart_rule1_rlt = chart_rule1_rlt + ruleCheckedRlt;

			//rule4: 连续14点交互着上线跳动

			int rule4AlternatingUpDownResult = 0;
			ruleCheckedRlt = "N";

			if ('Y' == rule4) {
				for (int i = 0; i < 12; i++) {
					Double valueA = values[MAX_SPC_VALUE_CNT - 1 - i];
					Double valueB = values[MAX_SPC_VALUE_CNT - 2 - i];
					Double valueC = values[MAX_SPC_VALUE_CNT - 3 - i];
					if(valueA == null || valueB == null || valueC == null){
						continue;
					}
					if ((valueA > valueB && valueB < valueC)
							|| (valueA < valueB && valueB > valueC)
							&& isEmpty(valueA)
							&& isEmpty(valueB) && isEmpty(valueC)) {
						rule4AlternatingUpDownResult++;
					}
				}
				if (rule4AlternatingUpDownResult >= 14) {
					ruleCheckedRlt = "Y";
				}

			}

			chart_rule1_rlt = chart_rule1_rlt + ruleCheckedRlt;

			//rule5: 连续三点 有两点落在2σ外

			ruleCheckedRlt = "N";
			int rule5Outof2SigmaCnt = 0;
			if ('Y' == rule5) {
				for (int i = 0; i < 3; i++) {
					Double tmpValue = values[MAX_SPC_VALUE_CNT - 1 - i];
					if(tmpValue == null){
						continue;
					}
					if (tmpValue > (target + ((ucl - target) / 3)*2)
							&& tmpValue < ucl) {
						rule5Outof2SigmaCnt++;
					}
					if (tmpValue < (target - ((target - lcl) / 3)*2)
							&& tmpValue > lcl) {
						rule5Outof2SigmaCnt++;
					}
				}
				if (rule5Outof2SigmaCnt >= 2) {
					ruleCheckedRlt = "Y";
				}
			}
			chart_rule1_rlt = chart_rule1_rlt + ruleCheckedRlt;

			//rule6: 连续5点中有四点落在1σ外

			ruleCheckedRlt = "N";
			int rule6OutOf1SigmaCnt = 0;

			if ('Y' == rule6) {
				for (int i = 0; i < 5; i++) {
					Double tmpValue = values[MAX_SPC_VALUE_CNT - 1 - i];
					if(tmpValue ==null){
						continue;
					}
					if (tmpValue > (target + (ucl - target) / 3)
							&& tmpValue < ucl) {
						rule6OutOf1SigmaCnt++;
					}
					if (tmpValue < (target - (target - lcl) / 3)
							&& tmpValue > lcl) {
						rule6OutOf1SigmaCnt++;
					}
				}
				if (rule6OutOf1SigmaCnt >= 4) {
					ruleCheckedRlt = "Y";
				}
			}

			chart_rule1_rlt = chart_rule1_rlt + ruleCheckedRlt;

			//rule7: 连续15点在中心线上线两侧1σ内

			ruleCheckedRlt = "N";
			int rule7Within1SigmaCnt = 0;
			if ('Y' == rule7) {
				for (int i = 0; i < 15; i++) {
					Double tmpValue = values[MAX_SPC_VALUE_CNT - 1 - i];
					if(tmpValue == null){
						continue;
					}
					if (tmpValue < target + (ucl - target) / 3
							&& tmpValue > target - (target - lcl) / 3) {
						rule7Within1SigmaCnt++;
					}
				}
				if (rule7Within1SigmaCnt >= 15) {
					ruleCheckedRlt = "Y";
				}
			}
			chart_rule1_rlt = chart_rule1_rlt + ruleCheckedRlt;
			spcRetChartInfo.setChart_rule_1_rlt(chart_rule1_rlt);

		}
		spcRetChartInfoDao.update(spcRetChartInfo);
		return spcRetChartInfo;
	}

	/*计算中位数： NO.02
	 * 1.数组排序  
	 * 2.取中间值 I=(n+1)/2 
	 * 3.若I为偶数，中位数为(第I个值+第I+1值)/2
	 * 4.若I为奇数，中位数为第I个值
	 */
	public Double getMedianArray(List<Double> valueList) {
		double temp = 0;
		int median = 0;
		int size = valueList.size();
		Double[] doubleArray = (Double[]) valueList.toArray(new Double[size]);
		sortArray(doubleArray);// 数组排序
		median = (size + 1) / 2; // 中间数
		if (median % 2 == 0) {
			temp = (doubleArray[median] + doubleArray[median + 1]) / 2;
		} else {
			temp = doubleArray[median];
		}
		return temp;
	}

	//NO.02 数组排序
	public void sortArray(Double[] array) {
		for (int i = 0; i < array.length; i++) {
			for (int j = i + 1; j < array.length; j++) {
				if (array[i] > array[j]) {
					double temp = array[i];
					array[i] = array[j];
					array[j] = temp;
				}
			}
		}
	}

	//NO.02 P图 中心线计算  
	public Double calucateP(Double sampsize, List<Double> valueList) {
		double avgDouble = 0;
		double total = 0;
		for (int i = 0; i < valueList.size(); i++) {
			total += total + sampsize * valueList.get(i);
		}
		avgDouble = total / sampsize * valueList.size();
		return avgDouble;
	}

	//NO.02 nP图 中心线计算
	public Double calucateNP(Double sampsize, List<Double> valueList) {
		double avgDouble = 0;
		double total = 0;
		for (int i = 0; i < valueList.size(); i++) {
			total += total + sampsize * valueList.get(i);
		}
		avgDouble = total / valueList.size();
		return avgDouble;
	}

	//NO.02 c图 中心线计算
	public Double calucateC(Double sampsize, List<Double> valueList) {
		double avgDouble = 0;
		double total = 0;
		for (int i = 0; i < valueList.size(); i++) {
			total += total + valueList.get(i);
		}
		avgDouble = total / valueList.size();
		return avgDouble;
	}
}
